#include "stdafx.h"
#include "../Utils/PropertyContainer.h"

namespace ja2{ namespace utils
{
	bool Section::exist(std::string const &Key) const
	{
		return (m_Properties.count(Key) == 1);
	}

	void Section::add(std::string const &Key, std::string const &Value)
	{
		m_Properties[Key].push_back(Value);
	}

	void Section::add(std::string const &Key)
	{
		m_Properties[Key];
	}

	void Section::set(std::string const &Key, std::string const &Value)
	{
		// Clear all previous values
		m_Properties[Key].clear();
		// Add value
		add(Key, Value);
	}

	bool Section::get_value(std::string const &Key, PropertiesVector_t &Values) const
	{
		// Key found
		if(exist(Key))
		{
			Values = get_value(Key);

			return true;
		}

		return false;
	}

	bool Section::get_value(std::string const &Key, std::string &Value) const
	{
		// Key found
		if(exist(Key))
		{
			PropertiesVector_t const &properties = get_value(Key);
			// There is some value
			if(!properties.empty())
				Value = properties.back();

			return true;
		}

		return false;
	}

	bool Section::get_value_default(std::string const &Key, std::string &Value, std::string const &Default) const
	{
		// Key found
		if(exist(Key))
		{
			PropertiesVector_t const &properties = get_value(Key);
			// Set value
			Value = (!properties.empty() ? properties.back() : Default);
			
			return true;
		}

		return false;
	}

	std::string Section::get_string_value(std::string const &Key, std::string const &Default) const
	{
		std::string value;
		// Get value
		get_value_default(Key, value, Default);
		
		return value;
	}

	bool Section::get_bool_value(std::string const &Key) const
	{
		std::string value;
		get_value(Key, value);

		return (value == "true");
	}

	bool Section::get_bool_value_default(std::string const &Key, bool Default) const
	{
		// Key found
		if(exist(Key))
			return get_bool_value(Key);
		
		return Default;
	}

	Section::StringVector_t Section::get_string_vector(std::string const &Key) const
	{
		return get_value(Key);
	}

	bool Section::get_string_vector(std::string const &Key, StringVector_t &Values) const
	{
		return get_value(Key, Values);
	}

	Section::PropertiesVector_t &Section::get_value(std::string const &Key)
	{
		return m_Properties[Key];
	}

	Section::PropertiesVector_t const &Section::get_value(std::string const &Key) const
	{
		return m_Properties.find(Key)->second;
	}

	std::int_least32_t Section::get_long_value(std::string const &Key) const
	{
		return Convert::string_to_int32(get_string_value(Key));
	}

	std::int_least32_t Section::get_long_value_default(std::string const &Key, long Default) const
	{
		// Key exist
		if(exist(Key))
			return get_long_value(Key);

		return Default;
	}
		
	void Section::print(std::ostream &Out, std::string const &Prefix) const
	{
		for(auto it = m_Properties.begin(), end = m_Properties.end(); it != end; ++it)
		{
			Out << Prefix << it->first << " = ";
			// Print all values
			for(auto it_values = it->second.begin(), it_values_end = it->second.end(); it_values != it_values_end; ++it_values)
				Out << *it_values << ", ";
			Out << std::endl;
		}
	}

	void Section::clear()
	{
		m_Properties.clear();
	}

	//--------------------------------//
	
	PropertyContainer::PropertyContainer(PropertyContainer &&Rvalue)
		: m_Sections(std::move(Rvalue.m_Sections))
	{
	}

	void PropertyContainer::clear()
	{
		m_Sections.clear();
	}

	bool PropertyContainer::section_exists(std::string const &Section) const
	{
		return (m_Sections.count(Section) == 1);
	}

	Section &PropertyContainer::get_section(std::string const &Section)
	{
		return m_Sections[Section];
	}

	Section const &PropertyContainer::get_section(std::string const &Section) const
	{
		if(!section_exists(Section))
			throw RuntimeException("Section '" + Section + "' doesn't exist.");

		return m_Sections.find(Section)->second;
	}

	void PropertyContainer::print(std::ostream &Out) const
	{
		for(auto it = m_Sections.begin(), end = m_Sections.end(); it != end; ++it)
		{
			Out << "[" << it->first << "]" << std::endl;
			it->second.print(Out, "  ");
			Out << std::endl;
		}
	}
} /*utils*/} /*ja2*/